﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using Microsoft.Phone.Reactive;

namespace desarrolloMobile.DGT
{
    [DataContract]
    public class DgtContexto : INotifyPropertyChanged, IDisposable
    {
        [DataMember]
        public ObservableCollection<Incidencia> Incidencias { get; set; }
        public ObservableCollection<Incidencia> IncidenciasTotal { get; set; }

        [DataMember]
        public DateTime Hora { get; set; }

        public DgtContexto()
            : this(3, incidencia => true)
        { }

        private Func<Incidencia, bool> _predicado;
        public Func<Incidencia, bool> Predicado
        {
            get
            {
                return _predicado;
            }
            set
            {
                _predicado = value;
                if (Incidencias != null)
                {
                    Incidencias = Incidencias
                        .Where(Predicado)
                        .ToObservableCollection();
                    NotifyPropertyChanged("Incidencias");
                    IsDataLoaded = true;
                    NotifyPropertyChanged("Vacio");
                }
            }
        }

        public bool Vacio
        {
            get
            {
                return !IsDataLoaded;
            }
        }

        public DgtContexto(int frecuencia, Func<Incidencia, bool> predicado)
        {
            Predicado = predicado;

            Observable.Timer(TimeSpan.Zero, TimeSpan.FromMinutes(frecuencia))
                .Select(_ => PrepararPeticion())
                .Switch()
                .ObserveOnDispatcher()
                .Subscribe(incidencias =>
                               {
                                   IncidenciasTotal = incidencias.ToObservableCollection();
                                   Incidencias = (incidencias
                                       .Where(Predicado))
                                       .ToObservableCollection();
                                   NotifyPropertyChanged("Incidencias");
                                   Hora = DateTime.Now;
                                   NotifyPropertyChanged("Hora");
                                   System.Diagnostics.Debug.WriteLine(DateTime.Now.ToLongTimeString() + " " +
                                                                      Incidencias.Count.ToString());
                                   IsDataLoaded = true;
                                   NotifyPropertyChanged("Vacio");
                               });
        }

        public void Actualizar()
        {
            Incidencias = IncidenciasTotal;
            NotifyPropertyChanged("Incidencias");
            IsDataLoaded = false;
            NotifyPropertyChanged("Vacio");
        }

        internal IObservable<IEnumerable<Incidencia>> PrepararPeticion()
        {
            return Observable.Defer(() =>
            {
                var webRequest =
                    WebRequest.Create(new Uri("http://dgt.es/incidencias.xml"));

                webRequest.Method = "POST";
                webRequest.ContentType = "text/XML";

                var peticion = Observable.FromAsyncPattern<WebResponse>(
                    webRequest.BeginGetResponse,
                    webRequest.EndGetResponse);

                return from elemento in peticion()
                    .Select(respuestaWeb =>
                    {
                        using (var rs = respuestaWeb.GetResponseStream())
                        {
                            return rs.Deserialize(respuestaWeb.ContentLength);
                        }
                    })
                       select elemento;
            });
        }
        
        public bool IsDataLoaded
        {
            get;
            set;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String propertyName)
        {
            var handler = PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public void Dispose()
        {
            
        }
    }
}
